package self.zhangkang.chart.service.main

import self.zhangkang.chart.data.KLineInfo
import java.math.BigDecimal

/**
 * @author : Android-张康
 * created on: 2023/6/28 14:51
 * description: 成本均线协助类
 */
object AverageCostTools {
    private const val MA_5 = 5
    private const val MA_13 = 13
    private const val MA_34 = 34

    fun calculationCYC(dataList: MutableList<KLineInfo>) {
        val getValue: (KLineInfo) -> Long = {
            it.turnVolume
        }
        val getVolume: (KLineInfo) -> Long = {
            it.volume
        }
        dataList.forEachIndexed { index, kLineInfo ->
            val cyc5 = calculationAverageCost(
                quoteList = dataList,
                n = MA_5,
                currentIndex = index,
                defaultValue = Float.NaN,
                getValue = getValue,
                getVolume = getVolume
            )
            val cyc13 = calculationAverageCost(
                quoteList = dataList,
                n = MA_13,
                currentIndex = index,
                defaultValue = Float.NaN,
                getValue = getValue,
                getVolume = getVolume
            )
            val cyc34 = calculationAverageCost(
                quoteList = dataList,
                n = MA_34,
                currentIndex = index,
                defaultValue = Float.NaN,
                getValue = getValue,
                getVolume = getVolume
            )
            dataList[index] = kLineInfo.copy(
                cyc = kLineInfo.cyc.copy(short = cyc5, mid = cyc13, long = cyc34)
            )
        }
    }

    /**
     * 计算当前日期成本均线
     *
     * @param quoteList K线数据列表
     * @param currentIndex 当前位置
     * @param n 周期
     * @param defaultValue 不满 [n] 周期时的默认值
     *
     * @return 返回当前位置的 [n] 周期成本均线，如果不满 [n] 周期，返回 [defaultValue]
     */
    @JvmStatic
    @JvmOverloads
    fun <T> calculationAverageCost(
        quoteList: List<T>,
        n: Int,
        currentIndex: Int,
        defaultValue: Float = Float.NaN,
        getValue: (T) -> Long,
        getVolume: (T) -> Long
    ): Float {
        if (currentIndex < n - 1) {
            return defaultValue
        }
        var sum = 0F
        val start = currentIndex - n + 1
        for (index in start..currentIndex) {
            val quoteInfo = quoteList[index]
            val value = BigDecimal(getValue(quoteInfo))
                .divide(BigDecimal(getVolume(quoteInfo)), 2, BigDecimal.ROUND_HALF_UP)
                .toFloat()
            sum += value
        }
        return sum / n
    }
}